package pers.tetris;

import java.util.Arrays;

/**
 * 俄罗斯方块的形状类
 * 提供了基础的旋转、碰撞检测的功能
 * @see Shape#rotate() 形状的旋转
 * @see Shape#borderTest(int[][], int, int)  碰撞检测
 * @see FixedShape
 */
public class Shape implements Cloneable{
    /**
     * 形状数组，要求长宽相等
     */
    private final int[][] initShape;
    /**
     * 当前的位置 x ,从左往右的偏移量
     */
    private int x;
    /**
     * 当前的位置 y, 从上向下的偏移量
     */
    private int y;

    /**
     * 创建形状
     * @param initShape 初始形状
     */
    public Shape(int[][] initShape){
        this.initShape = initShape;
        this.x = 3;
        this.y = -2;
    }

    /**
     * 对当前形状顺时针旋转90度
     */
    public void rotate(){
        /*
          layer 是第几层，二维数组从外向内的层数
          例如一个矩阵：
          [a   b   c   d
           e   f   g   h
           i   j   k   l
           m   n   o   p]
           旋转90度，对于 a就是 将a 移到d ,d→p,p→m,m→a ，写成代码就是：
           tmp = a, a = m, m = p, p = d ,d = a, a = tmp
           类似的 对于b、c 也需要做 这样的操作
           所以第layer层 需要做 initShape.length - layer - 1 次操作
         */
        for (int layer = 0; layer < initShape.length / 2; ++layer) {
            // last 是
            int last = initShape.length - layer - 1;
            for (int i = layer; i < last; ++i) {
                int tmp = initShape[layer][i];
                initShape[layer][i] = initShape[last - i + layer][layer];
                initShape[last - i + layer][layer] = initShape[last][last - i + layer];
                initShape[last][last - i + layer] = initShape[i][last];
                initShape[i][last] = tmp;
            }
        }
    }

    /**
     * 边界测试--如果形状出现在（xOffset，yOffset）的位置，是否会发生碰撞
     * @param map 地图数组
     * @param xOffset 横向的偏移量
     * @param yOffset 纵向的偏移量
     * @return 如果碰撞，返回true, 否则返回false
     */
    public boolean borderTest(int[][] map,int xOffset,int yOffset){
        int[][] shape = getShape();
        for (int i = 0; i < shape.length; i++) { // i是y 纵向
            for (int j = 0; j < shape[i].length; j++) { // j 是 x 横向
                if (shape[i][j]==0){
                    continue;
                }
                /**
                 * 判断条件说明：
                 * xOffset+j<0 即超过了地图左边界
                 * xOffset+j >= TetrisModel.COLS  超过了地图右边界
                 * yOffset+i >= TetrisModel.ROWS 超过了地图下边界
                 * yOffset+i>=0 && map[yOffset+i][xOffset+j]!=0  在地图范围内且地图的这个位置有方块
                 */
                if (xOffset+j<0 || xOffset+j >= TetrisModel.COLS ||
                        yOffset+i >= TetrisModel.ROWS ||
                        (yOffset+i>=0 && map[yOffset+i][xOffset+j]!=0)){
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return "Shape{" +
                "shape=" + Arrays.deepToString(initShape) +
                '}';
    }

    public int[][] getShape() {
        return initShape;
    }

    @Override
    public Shape clone() {
        try {
            Shape clone = (Shape) super.clone();
            if (initShape!=null){
                for (int i = 0; i < initShape.length; i++) {
                    clone.initShape[i] = initShape[i].clone();
                }
            }
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}
